package com.yfp.client.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.DeviceCurrentComboStock;
import com.yfp.client.domain.OrderCombo;
import com.yfp.client.domain.OrderDetail;
import com.yfp.client.domain.dto.ShoppingCartsDto;
import com.yfp.client.mapper.DeviceCurrentComboStockMapper;
import com.yfp.client.service.DeviceCurrentComboStockService;
import com.yfp.client.service.DeviceServer;
import com.yfp.client.service.SysOperationLogService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【device_current_combo_stock】的数据库操作Service实现
 * @createDate 2024-06-05 13:47:14
 */
@Service
@Slf4j
public class DeviceCurrentComboStockServiceImpl extends ServiceImpl<DeviceCurrentComboStockMapper, DeviceCurrentComboStock> implements DeviceCurrentComboStockService {

    @Resource
    private DeviceCurrentComboStockMapper deviceCurrentComboStockMapper;
    @Resource
    private DeviceServer deviceServer;
    @Resource
    private SysOperationLogService sysOperationLogService;

    @Override
    public Boolean checkStockAvailability(List<ShoppingCartsDto> shoppingCartList, String machineId) {
        List<String> packageIds = shoppingCartList.stream().map(ShoppingCartsDto::getPackageId).collect(Collectors.toList());
        List<DeviceCurrentComboStock> deviceCurrentComboStocks = deviceCurrentComboStockMapper.listByPackageIdsAndMachineId(packageIds, machineId);
        if (!NumberUtil.equals(CollUtil.size(packageIds), CollUtil.size(deviceCurrentComboStocks))) {
            return false;
        }

        for (ShoppingCartsDto shoppingCart : shoppingCartList) {
            for (DeviceCurrentComboStock deviceCurrentComboStock : deviceCurrentComboStocks) {
                if (shoppingCart.getPackageId().equals(deviceCurrentComboStock.getComboId())) {
                    if (shoppingCart.getQuantity() > Optional.ofNullable(deviceCurrentComboStock.getComboNum()).orElse(0)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 减少库存
     *
     * @param shoppingCartList
     * @param machineId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void decreaseStockQuantity(List<ShoppingCartsDto> shoppingCartList, String machineId) {
        List<String> packageIds = shoppingCartList.stream().map(ShoppingCartsDto::getPackageId).collect(Collectors.toList());
        List<DeviceCurrentComboStock> deviceCurrentComboStocks = deviceCurrentComboStockMapper.listByPackageIdsAndMachineId(packageIds, machineId);
        Map<String, DeviceCurrentComboStock> stockMapByPackageId = deviceCurrentComboStocks.stream().collect(Collectors.toMap(DeviceCurrentComboStock::getComboId, item -> item));

        Map<String, Integer> shoppingMapByPackageId = shoppingCartList.stream().collect(Collectors.groupingBy(ShoppingCartsDto::getPackageId, Collectors.summingInt(ShoppingCartsDto::getQuantity)));
        List<DeviceCurrentComboStock> newStocks = shoppingMapByPackageId.entrySet().stream().map(entry -> {
            String packageId = entry.getKey();
            Integer quantity = entry.getValue();
            if (!stockMapByPackageId.containsKey(packageId)) {
                throw new RuntimeException("库存不足");
            }
            DeviceCurrentComboStock deviceCurrentComboStock = stockMapByPackageId.get(packageId);
            if (deviceCurrentComboStock.getComboNum() < quantity) {
                throw new RuntimeException("库存不足");
            }
            deviceCurrentComboStock.setComboNum(deviceCurrentComboStock.getComboNum() - quantity);
            return deviceCurrentComboStock;
        }).collect(Collectors.toList());

        this.updateBatchById(newStocks);

        // 将库存信息发送到设备
        deviceServer.sendStockInfo(machineId, newStocks);
    }

    /**
     * 缺少的套餐数量
     *
     * @param shoppingCartList
     * @param machineId
     * @return
     */
    @Override
    public List<ShoppingCartsDto> lackList(List<ShoppingCartsDto> shoppingCartList, String machineId) {
        List<String> packageIds = shoppingCartList.stream().map(ShoppingCartsDto::getPackageId).collect(Collectors.toList());
        Map<String, Integer> stockMapById = deviceCurrentComboStockMapper.listByPackageIdsAndMachineId(packageIds, machineId).stream().collect(Collectors.toMap(DeviceCurrentComboStock::getComboId, item -> item.getComboNum()));
        List<ShoppingCartsDto> lackList = shoppingCartList.stream().map(item -> {
            Integer count = MapUtil.getInt(stockMapById, item.getPackageId(), 0);
            if (count < item.getQuantity()) {
                ShoppingCartsDto shoppingCartsDto = new ShoppingCartsDto();
                shoppingCartsDto.setPackageName(item.getPackageName());
                shoppingCartsDto.setPackageId(item.getPackageId());
                shoppingCartsDto.setQuantity(item.getQuantity() - count);
                return shoppingCartsDto;
            }
            return null;
        }).filter(item -> item != null).collect(Collectors.toList());
        return lackList;
    }

    /**
     * 恢复库存
     *
     * @param orderCombo
     * @param orderDetails
     */
    @Override
    public void recoverStockQuantity(OrderCombo orderCombo, List<OrderDetail> orderDetails) {

        String machineId = orderCombo.getMachineId();
        // 是否存在报损
        if (sysOperationLogService.existBreakage(machineId)){
            return;
        }

        List<String> packageIds = orderDetails.stream().map(OrderDetail::getPackageId).collect(Collectors.toList());
        List<DeviceCurrentComboStock> deviceCurrentComboStocks = deviceCurrentComboStockMapper.listByPackageIdsAndMachineId(packageIds, orderCombo.getMachineId());
        Map<String, DeviceCurrentComboStock> stockMapByPackageId = deviceCurrentComboStocks.stream().collect(Collectors.toMap(DeviceCurrentComboStock::getComboId, item -> item));


        Map<String, Long> detailsMapByPackageId = orderDetails.stream().collect(Collectors.groupingBy(OrderDetail::getPackageId, Collectors.summingLong(OrderDetail::getCount)));
        List<DeviceCurrentComboStock> newStocks = detailsMapByPackageId.entrySet().stream().map(entry -> {
            String packageId = entry.getKey();
            Long quantity = entry.getValue();
            DeviceCurrentComboStock deviceCurrentComboStock = stockMapByPackageId.getOrDefault(packageId, new DeviceCurrentComboStock());
            deviceCurrentComboStock.setComboNum((int) (Optional.ofNullable(deviceCurrentComboStock.getComboNum()).orElse(0) + quantity));
            log.info("套餐id:{},补充后数量:{}",packageId,deviceCurrentComboStock.getComboNum());
            return deviceCurrentComboStock;
        }).collect(Collectors.toList());

        this.updateBatchById(newStocks);

        // 将库存信息发送到设备
        deviceServer.sendStockInfo(orderCombo.getMachineId(), newStocks);
    }

    /**
     * 根据设备id查询套餐库存
     *
     * @param machineId
     * @return
     */
    @Override
    public List<DeviceCurrentComboStock> getByMachineId(Long machineId) {
        return deviceCurrentComboStockMapper.listByMachineId(machineId);
    }
}




